// $URL: http://mingw-lib.googlecode.com/svn/trunk/working/nam/nam.cpp $
// $Rev: 683 $
// $Author: akio.miyoshi $
// $Date:: 2012-06-16 09:31:46 +0000#$

#include "nam.h"
#include "nbr.h"

#include <QtCore>
#include <QtGui>
#include <QtNetwork>
//#include "private/qnetworkaccesshttpbackend_p.h"

NetworkAccessManager::NetworkAccessManager(NetworkThreadRequest *a_independent, QObject *parent)
    : QNetworkAccessManager(parent)
    , m_independent(a_independent)
	, m_factory(0)
{
    connect(this, SIGNAL(authenticationRequired(QNetworkReply*,QAuthenticator*)),
            SLOT(authenticationRequired(QNetworkReply*,QAuthenticator*)));
    connect(this, SIGNAL(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)),
            SLOT(proxyAuthenticationRequired(QNetworkProxy,QAuthenticator*)));
    connect(this, SIGNAL(finished(QNetworkReply*)),
            SLOT(requestFinished(QNetworkReply*)));
#ifndef QT_NO_OPENSSL
    connect(this, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
            SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
#endif
#if 0x0
    if (!m_independent)
    {
        QNetworkDiskCache *diskCache = new QNetworkDiskCache(this);
        QString location = QDesktopServices::storageLocation(QDesktopServices::CacheLocation);
        diskCache->setCacheDirectory(location);
        qDebug() << "[location]" << location;
        setCache(diskCache);
    }
#endif
}

void NetworkAccessManager::setBackendFactory(NetworkAccessBackendFactory *a_factory)
{
	m_factory = a_factory;
}

void NetworkAccessManager::addToSilentList(QString v_url_begin)
{
    m_silentList.append(v_url_begin);
}

void NetworkAccessManager::addToSilentList(QRegExp *v_url_rx)
{
	m_silentRx.append(v_url_rx);
}

bool NetworkAccessManager::isInSilentList(QUrl v_url)
{
	m_mutex.lock();
	QString v_url_str = v_url.toString();
	//foreach(QString v_silent, m_silentList)
	for(int i=0; i<m_silentList.size(); i++)
	{
		QString v_silent = m_silentList.value(i);
		if(v_url_str.startsWith(v_silent))
        {
			m_mutex.unlock();
			return true;
        }
    }
	//foreach(QRegExp v_silent, m_silentRx)
	for(int i=0; i<m_silentRx.size(); i++)
	{
		QRegExp *v_silent = m_silentRx.value(i);
		if(v_silent->indexIn(v_url_str) != -1)
		{
			m_mutex.unlock();
			return true;
		}
	}
	m_mutex.unlock();
	return false;
}

#if 0x0
QNetworkReply *NetworkAccessManager::createRequest(Operation op, const QNetworkRequest & req, QIODevice * outgoingData)
{
	QNetworkRequest request = req; // copy so we can modify
	qDebug() << "NetworkAccessManager::createRequest()" << op << request.url();
	// this is a temporary hack until we properly use the pipelining flags from QtWebkit
    // pipeline everything! :)
    if(!isInSilentList(req.url()))
    {
		qDebug() << "NetworkAccessManager::createRequest()" << op << request.url();
    }
    request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
	//return QNetworkAccessManager::createRequest(op, request, outgoingData);
	return QNetworkAccessManager::createRequest(op, request, outgoingData, 0);
}
#endif

QNetworkReply *NetworkAccessManager::createRequest (
		Operation op,
		const QNetworkRequest & req,
		QIODevice * outgoingData
//#ifdef QT_BACKEND_BUILD
//		,QObject *backend
//#endif
		)
{
	////qDebug() << "NetworkAccessManager::createRequest()";
	QNetworkRequest request = req; // copy so we can modify
	// this is a temporary hack until we properly use the pipelining flags from QtWebkit
	// pipeline everything! :)
	if(!isInSilentList(req.url()))
	{
		qDebug() << "NetworkAccessManager::createRequest()" << op << request.url();
		QList<QByteArray> v_headerList = request.rawHeaderList();
		foreach(QByteArray v_first, v_headerList)
		{
			QByteArray v_second = request.rawHeader(v_first);
			qDebug() << v_first << v_second;
		}
	}
	request.setAttribute(QNetworkRequest::HttpPipeliningAllowedAttribute, true);
    QObject *backend = NULL;
        //if(!backend)
	{
		if(m_factory)
		{
			backend = m_factory->create(op, request);
		}
	}
    return QNetworkAccessManager::createRequestWithBackend(op, request, outgoingData, backend);
}

void NetworkAccessManager::authenticationRequired(QNetworkReply *reply, QAuthenticator *auth)
{
}

void NetworkAccessManager::proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *auth)
{
}

#ifndef QT_NO_OPENSSL
void NetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &error)
{
}
#endif

void NetworkAccessManager::requestFinished(QNetworkReply *reply)
{
    if (m_independent)
    {
        ////qDebug() << "NetworkAccessManager::requestFinished(): before exit()";
        ////m_independent->QThread::exit(0);
        m_independent->replyFinished();
        ////qDebug() << "NetworkAccessManager::requestFinished(): after exit()";
    }
    QString v_url_str = reply->request().url().toString();
    if(isInSilentList(reply->request().url())) return;
    {
        qDebug() << "NetworkAccessManager::requestFinished()" << reply->request().url();
        QList<QByteArray> headerList = reply->rawHeaderList();
        foreach(QByteArray ba, headerList)
        {
#if 0x0
            if (ba != "Content-Type" && ba != "Content-Length")
            {
                continue;
            }
#endif
            QByteArray headerData = reply->rawHeader(ba);
            qDebug() << ba << headerData;
        }
    }
}

QByteArray NetworkAccessManager::doGet(QString a_url, QString *a_contentType)
{
    QUrl v_url;
    v_url.setUrl(a_url);
    return this->doGet(v_url, a_contentType);
}

QByteArray NetworkAccessManager::doGet(QUrl a_url, QString *a_contentType)
{
    QNetworkRequest v_request;
    v_request.setUrl(a_url);
    return this->doGet(v_request, a_contentType);
}

QByteArray NetworkAccessManager::doGet(QNetworkRequest request, QString *a_contentType)
{
    qDebug() << "doGet()" << request.url();
    QNetworkReply *v_reply = this->get(request);
    QByteArray v_response;
    NetworkBatchRequest *v_nbr = new NetworkBatchRequest(v_reply, &v_response, false);
    v_nbr->wait();
    if(a_contentType)
    {
        QByteArray v_contentType = v_reply->rawHeader("Content-Type");
        qDebug() << "[v_contentType]" << v_contentType;
        (*a_contentType) = v_contentType;
    }
    delete v_reply;
    delete v_nbr;
    return v_response;
}

QByteArray NetworkAccessManager::doPost(QNetworkRequest request, QByteArray postData)
{
    qDebug() << "doPost()" << request.url();
    QBuffer v_postBuffer;
    v_postBuffer.setBuffer(&postData);
    QNetworkReply *v_reply = this->post(request, &v_postBuffer);
    QByteArray v_response;
    NetworkBatchRequest *v_nbr = new NetworkBatchRequest(v_reply, &v_response, false);
    v_nbr->wait();
    delete v_reply;
    delete v_nbr;
    return v_response;
}

//QNetworkReply *NetworkAccessManager::doGetReply(QNetworkRequest request)
QMap<QByteArray, QByteArray> NetworkAccessManager::doGetHead(QNetworkRequest request)
{
    qDebug() << "doGetHead()" << request.url();
    QNetworkReply *v_reply = this->get(request);
    QByteArray v_response;
    NetworkBatchRequest *v_nbr = new NetworkBatchRequest(v_reply, &v_response, true);
    v_nbr->wait();
    QMap<QByteArray, QByteArray> v_map;
    QList<QByteArray> v_headerList = v_reply->rawHeaderList();
    foreach(QByteArray v_headerName, v_headerList)
    {
        QByteArray v_headerData = v_reply->rawHeader(v_headerName);
        ////qDebug() << v_headerName << v_headerData;
        v_map.insert(v_headerName, v_headerData);
    }
    delete v_reply;
    delete v_nbr;
    return v_map;
}

int NetworkAccessManager::batDelete(QNetworkRequest request)
{
	qDebug() << "doDelete()" << request.url();
	QNetworkReply *v_reply = this->deleteResource(request);
	QByteArray v_response;
	NetworkBatchRequest *v_nbr = new NetworkBatchRequest(v_reply, &v_response, false);
	v_nbr->wait();
	QVariant v_status_code = v_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
	qDebug() << "[v_response]" <<v_response;
	delete v_reply;
	delete v_nbr;
	return v_status_code.toInt();
}

int NetworkAccessManager::batPost(QNetworkRequest request, QByteArray &postData, QByteArray &responsdData)
{
	qDebug() << "batPost()" << request.url();
	QBuffer v_postBuffer;
	v_postBuffer.setBuffer(&postData);
	QNetworkReply *v_reply = this->post(request, &v_postBuffer);
	NetworkBatchRequest *v_nbr = new NetworkBatchRequest(v_reply, &responsdData, false);
	v_nbr->wait();
	QVariant v_status_code = v_reply->attribute(QNetworkRequest::HttpStatusCodeAttribute);
	delete v_reply;
	delete v_nbr;
	return v_status_code.toInt();
}
